package com.ajavaer.framework.core.request;

import com.ajavaer.framework.common.message.PageMessage;
import com.ajavaer.framework.common.tools.ObjectTools;
import com.ajavaer.framework.common.tools.StringTools;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PagingRequest {
    protected Integer page = 1;
    protected Integer limit = 15;
    protected Map<String, Object> search = new HashMap<>();
    protected Map<String, String> sortBy = new HashMap<>();
    protected List<RequestHandler> searchHandlers = new ArrayList<>();

    public PagingRequest() {
    }

    /**
     * get动态请求
     *
     * @param page
     * @param limit
     * @param query 查询规则,eg:query=EQ_name__张三
     * @param sort 排序规则,eg:sort=id_asc,name_desc
     */
    public PagingRequest(Integer page, Integer limit, String query, String sort) {
        setPage(page == null ? 1 : page);
        setLimit(limit == null ? 15 : limit);
        if (StringTools.isNotBlank(sort)) {
            String[] sortArr = sort.split(",");
            Map<String, String> sortByMap = new HashMap<>();
            for (String s : sortArr) {
                if(!s.contains("_")){
                    s+="_asc";
                }
                String option = s.substring(s.lastIndexOf("_"));
                if ("_asc/_desc".contains(option)) {
                    sortByMap.put(s.substring(0, s.indexOf("_")), option.equals("_desc") ? "desc" : "asc");
                }
            }
            setSortBy(sortByMap);
        }
        if (StringTools.isNotBlank(query)) {
            String[] queryArr = query.split(",");
            Map<String, Object> search = new HashMap<>();
            for (String q : queryArr) {
                String[] item = q.split("__");
                if (item.length == 2) {
                    search.put(item[0], item[1]);
                }
            }
            setSearch(search);
        }
    }

    /**
     * 增加查询前处理句柄(责任链)
     *
     * @param handler
     */
    public void addHandlers(RequestHandler handler) {
        searchHandlers.add(handler);
    }

    public void searchhandler() {
        for (RequestHandler handler : searchHandlers) {
            handler.handler(search);
        }
    }

    /**
     * 增加排序规则
     *
     * @param propertie
     * @param direction
     * @return
     */
    public PagingRequest addSort(String propertie, String direction) {
        sortBy.put(propertie, direction);
        return this;
    }

    /**
     * 增加查询规则
     *
     * @param expression
     * @param value
     * @return
     */
    public PagingRequest addSearch(String expression, Object value) {
        search.put(expression, value);
        return this;
    }

    public Sort sort() {
        if (ObjectTools.isNotBlank(this.sortBy)) {
            Sort sort = null;
            for (Map.Entry<String, String> sortBy : sortBy.entrySet()) {
                String name = sortBy.getKey();
                String direction = sortBy.getValue();
                Sort sortAnd = Sort.by(Sort.Direction.fromString(direction), name);
                if (sort == null) {
                    sort = sortAnd;
                } else {
                    sort = sort.and(sortAnd);
                }
            }
            if (sort == null) {
                return Sort.unsorted();
            } else {
                return sort;
            }
        }
        return Sort.unsorted();
    }

    /**
     * 根据jpa返回和当前分页请求生成分页消息
     *
     * @param page
     * @param <T>
     * @return
     */
    public <T> PageMessage toPageMessage(Page<T> page) {
        return PageMessage.of(this.page, this.limit, page.getTotalElements(), page.getContent());
    }

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Integer getLimit() {
        return limit;
    }

    public void setLimit(Integer limit) {
        this.limit = limit;
    }

    public Map<String, String> getSortBy() {
        return sortBy;
    }

    public void setSortBy(Map<String, String> sortBy) {
        this.sortBy = sortBy;
    }

    public List<RequestHandler> getSearchHandlers() {
        return searchHandlers;
    }

    public void setSearchHandlers(List<RequestHandler> searchHandlers) {
        this.searchHandlers = searchHandlers;
    }

    public Map<String, Object> getSearch() {
        return search;
    }

    public void setSearch(Map<String, Object> search) {
        this.search = search;
    }
}
